package com.jbp.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jbp.exception.RRException;
import com.jbp.model.LoginLog;
import com.jbp.model.LoginParam;
import com.jbp.model.User;
import com.jbp.model.Wallet;
import com.jbp.redis.RedisConfigService;
import com.jbp.utils.*;
import com.jbp.utils.encryptUtils.RsaEncryptUtil;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class LoginService {
    @Autowired
    private UserService userService;
    @Autowired
    private WalletService walletService;
    @Autowired
    private TecentMsgService tecentMsgService;
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private RedisConfigService redisConfigService;
    @Autowired
    private LoginLogService loginLogService;
    @Autowired
    private PropertyService propertyService;
    @Autowired
    private WxLoginUtil wxLoginUtil;
    @Autowired
    private QqLoginUtil qqLoginUtil;
    /**本机号码一键登录*/
    public User localPhoneLogin(LoginParam loginParam) {
        String phone = getPhoneByToken(loginParam.getLoginToken());
        if (StringUtils.isEmpty(phone)) {
            throw new RRException("手机号获取失败");
        }
        User usercheck = userService.getOne(new QueryWrapper<User>().eq("mobile", phone));
        if (usercheck == null) {
            User user = new User();
            user.setMobile(phone);
            usercheck = createUser(user);
        }

        usercheck.setDevice(loginParam.getDevice());
        usercheck.setAesKey(loginParam.getAesKey());
        usercheck.setAesVipara(loginParam.getAesVipara());
        return this.login(usercheck, loginParam,"本机号码");
    }

    public User wechatLogin(LoginParam loginParam) {
        // 1. 调用微信登录接口
        Map<String, Object> userInfo = wxLoginUtil.getWechatUserInfo(loginParam.getCode());
        String openId = (String) userInfo.get("openid");
        String nickname = (String) userInfo.get("nickname");
        String img = (String) userInfo.get("headimgurl");

        User usercheck = userService.getOne(new QueryWrapper<User>().eq("wechat_id", openId));

        if (usercheck == null) {
            User user = new User();
            user.setWechatId(openId);
            user.setWechatName(nickname);
            user.setName(nickname);
            user.setImg(img);
            usercheck = createUser(user);
        }

        usercheck.setDevice(loginParam.getDevice());
        usercheck.setAesKey(loginParam.getAesKey());
        usercheck.setAesVipara(loginParam.getAesVipara());
        return this.login(usercheck, loginParam,"wechat");
    }

    /**
     * qq登录和微信登录，都是会接收前端的code参数，在查询qq/wechat接口后，如果正常，
     * 后面的逻辑都是比较接近的：判断是否注册，如果没有注册，走注册逻辑；如果注册了，走登录逻辑。
     */
    public User qqLogin(LoginParam loginParam) {
        Map<String, Object> userInfo = qqLoginUtil.getQqUserInfo(loginParam);
        String openId = (String) userInfo.get("openid");
        String nickname = (String) userInfo.get("nickname");

        User usercheck = userService.getOne(new QueryWrapper<User>().eq("qq_id", openId));
        if (usercheck == null) {
            User user = new User();
            user.setQqId(openId);
            user.setQqName(nickname);
            user.setName(nickname);
            if (StringUtils.isNotEmpty((String) userInfo.get("figureurl_qq_2"))) {
                user.setImg((String) userInfo.get("figureurl_qq_2"));
            } else {
                user.setImg((String) userInfo.get("figureurl_qq_1"));
            }
            usercheck = createUser(user);
        }

        usercheck.setDevice(loginParam.getDevice());
        usercheck.setAesKey(loginParam.getAesKey());
        usercheck.setAesVipara(loginParam.getAesVipara());
        return this.login(usercheck, loginParam,"qq");
    }

    public User appleLogin(LoginParam loginParam) {
        String appleUserId = loginParam.getAppleUserId();
        User usercheck = userService.getOne(new QueryWrapper<User>().eq("apple_user_id", appleUserId));
        if (usercheck == null) {
            User user = new User();
            user.setAppleUserId(appleUserId);
            usercheck = createUser(user);
        }

        usercheck.setDevice(loginParam.getDevice());
        usercheck.setAesKey(loginParam.getAesKey());
        usercheck.setAesVipara(loginParam.getAesVipara());
        return this.login(usercheck, loginParam, "ios");
    }

    @Transactional
    public synchronized User login(User user, LoginParam loginParam, String loginType) {
//        User usercheck=userService.getOne(new QueryWrapper<User>().eq("mobile",user.getMobile()));

//        usercheck.setDevice(user.getDevice());
        user.setIsOnline("online");
        String ip = IPReqUtil.getIpAddr(request);
        if (StringUtils.isNotEmpty(ip)) {
            user.setIp(ip);
        }
//        usercheck.setAesVipara(user.getAesVipara());
//        usercheck.setAesKey(user.getAesKey());
        user.setUpdateTime(new Date());
        userService.updateById(user);

        // 记录登录日志
        this.createLoginLog(user.getId(), user.getDevice(), ip, loginParam, loginType);
        BeanUtils.copyProperties(user,user);

        user.setType("normal");
        user.setPassword("");
        user.setSalt("");
        String sessionId= UUIDUtil.creatUUID();
        String token=user.getCode();
        user.setToken(token);
        user.setSessionId(sessionId);

        redisConfigService.set(token,sessionId);

        //同步腾讯
        tecentMsgService.addUser(user.getId());
        tecentMsgService.addUser(user.getId());
        /**
         * 清除验证码缓存
         */
        redisConfigService.remove(Constant.CODE_PREFIX+user.getMobile());
        return user;
    }

    public User createUser(User user) {
        /**
         * 注册
         */
        //生成邀请码
        String code = UUIDUtil.inviteCode();
        while (true) { //确保邀请码唯一
            if(!isCodeExits(code)) {
                user.setCode(code);
                break;
            } else {
                code = UUIDUtil.inviteCode();
            }
        }
        user.setSalt(code);
        /**
         * 生成靓号
         */
        String uuid= CreateUUid.createCode();
        while (true) { //确保uuid唯一
            if(!isUuidExits(uuid)) {
                user.setUuid(uuid);
                break;
            } else {
                uuid = CreateUUid.createCode();
            }
        }
        user.setIsOnline("online");
        user.setCreateTime(new Date());
        user.setType("normal");
        userService.save(user);


        //生成钱包
        Wallet wallet = new Wallet();
        wallet.setUserId(user.getId());
        wallet.setCreateTime(new Date());
        walletService.save(wallet);

//        tecentMsgService.addUser(user.getId());
//        tecentMsgService.addUser(user.getId());
//        tecentMsgService.addUser(user.getId());
        return user;
    }

    private void createLoginLog(Integer userId, String device, String ip, LoginParam loginParam, String loginType){
        // 记录登录日志，为避免登录日志记录出现异常，影响正常登录逻辑，所以忽略登录日志记录的异常
        try {
            LoginLog loginLog = new LoginLog();
            loginLog.setLoginTime(new Date());
            loginLog.setUserId(userId);
            loginLog.setDevice(device);
            loginLog.setPort(IPReqUtil.getRemotePort(request));
            loginLog.setIp(ip);
            loginLog.setLoginType(loginType);
            loginLog.setDeviceType(loginParam.getDeviceType());
            loginLog.setDeviceInfo(loginParam.getDeviceInfo());
            loginLog.setChannel(loginParam.getChannel());
            loginLog.setAppVersion(loginParam.getAppVersion());
            loginLogService.save(loginLog);
        } catch (Exception e) {
        }
    }


    public boolean isCodeExits(String code) {
        QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("code",code);
        return userService.getOne(queryWrapper) != null;
    }

    public boolean isUuidExits(String uuid) {
        QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("uuid",uuid);
        return userService.getOne(queryWrapper) != null;
    }

    /**一键登录 通过token取手机号*/
    private String getPhoneByToken(String loginToken){
        final String appKey = "c507e5e0af5f1dd115c7d501";
        final String masterSecret = "4f339e696c88879944d8703b";
        final String rsaPrivateKey = propertyService.getV("encrypt_private_key");
//        final String rsaPrivateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJHLpIEWsLIl/aPdXewHt7UenFVyk6o6IUiR8klt8/B4i2Mnxxw2DdMiI3t3HY0Zh++XZ6rOUmyO83h/m424Y/1riGdSgusIzGy7KhqHwZqFyMau49QPi3Ks6qgqoQeDN/3Xsre0cpdG5pxb8ENGCnqv8kVxPGeiZj0pgJXjnlHnAgMBAAECgYEAhdTYYgLxGecTyFrI/4QqF2FNAobVk9oeeV43eT4sQZ513QRDmtrnn9rjlU9HWiGIjd9+suUH9kzWo9MHeHU9mpoJf6IuvJYje3+Ec/ydkBZGdsPJnzdMXtrEF5v2SQUGMDbdjH1c9JhPQf/JHXca1VF5ubzSWPkEkJmSYj4heGECQQDd11BQkpXojPgNyKyw/DNUZfc65c49Ti1igovuZNpmS1sOpvxSSxAZmazZcJfAWFBKRaICOKCBmqkmr++PNKrXAkEAqD617SzYW8SJP3Fa1p2WMKxIpCp4Y7Lm2abfFuCgNzjGzGiZnxxorFZZ+I41qOdec7iiKciQocyhgRbsjMw/cQJBAM3cUJt0a8gxiL7Byf8zCi73sETnnEsnkNYpbtD6pfDnXMhsDRoQrhATm2LsKOZFDbzegUiuY8PhUbak7RlnNmECQClWLxC04fu6EBacXTs5wLr4uWhMXwPv4rQ7Qbi3O+YVdxKl6IilTDp7hOOC3UBAiH5aMM2fT5nRUyUKYtg9HqECQGvSyX3qX1z/teNCjawKnfxeH9Xo0M32PmRi5hS80zBvRgQqgfyaocrlvvjiArVBtwne1Eycc4xWBtQAK5DTpTk=";

        String plainCredentials = appKey + ":" + masterSecret;
        String base64Credentials = new String(Base64.encodeBase64(plainCredentials.getBytes()));

        Map<String, Object> head = new HashMap<>();
        head.put("Authorization", "Basic " + base64Credentials);

        Map<String, Object> params = new HashMap<>();
        String url = "https://api.verification.jpush.cn/v1/web/loginTokenVerify";
        params.put("loginToken", loginToken);

        String result = HttpClient.doPostJson(params, head, url);
        System.out.println("result:"+result);
        ObjectMapper mapper = new ObjectMapper();
        try {

            Map<String, String> map = mapper.readValue(result, Map.class);
            String encryptedPhone = map.get("phone");
            if(encryptedPhone!=null) {
                return RsaEncryptUtil.decrypt(encryptedPhone, rsaPrivateKey);
            }
            return null;
        } catch (IOException e) {
            throw new RRException("获取手机号失败");
        }
    }

    public static void main(String[] args) {
        String phoneByToken = new LoginService().getPhoneByToken("Lng5MvU46kPpRx/3gceefeOZ5J35W+vzBsJca+LV/qZMgl8w0vJ2dgKsPL7DOnXYaFO8X7d5hZ5bUf7ie/5gJNKk8yzAY3CunNPW3DQBD+/8nuGX9CjD8yOmh8x4SyfSegPfbzrgtcoOydHT2/ITXnI2gymII2s30oy+WVM8TC2J1FlgF2mwuELtWsjK0GkTIg0Ae/Jdu3i0hK8PP1dM7jVfh/tGBLaYFbEDdrrgLy8QaEU9iX7FroG5Rpgo/z9ibLEG6HhJM9Z+/e0RnIjSrq1xHp0Au/cDy6u/GDhPP3MnNxSQgP0f/ooJkZjz0daTyja/HrepsHXnFyaAbNqruZa78HGiOhs0Gah/N8cdZbzAIFZg74UI2YrH+jXNLzpj");
        System.out.println(phoneByToken);

//        String src = "1234567";
//        String pubKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCRy6SBFrCyJf2j3V3sB7e1HpxVcpOqOiFIkfJJbfPweItjJ8ccNg3TIiN7dx2NGYfvl2eqzlJsjvN4f5uNuGP9a4hnUoLrCMxsuyoah8GahcjGruPUD4tyrOqoKqEHgzf917K3tHKXRuacW/BDRgp6r/JFcTxnomY9KYCV455R5wIDAQAB";
//        String encrypt = RsaEncryptUtil.encrypt(src, pubKey);
//        System.out.println("encrypt: "+ encrypt);
//        //        String encryptedPhone = "QM330EF/7vsmScWbsitMs/qLszElue+WYMivKSb5aXM3MQs4MKD20xTdJ2ha+RiVTe+Jl+v45zx+hKUKc6Q/Hlh88Xt23A1qX/t+WibcWW95qUdFVYCrn/FnHePIOAAy7g2WfJt2zjoKYnh08hBzJ7GCs/0da+RhNAY64lPJruI=";
//        final String rsaPrivateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJHLpIEWsLIl/aPdXewHt7UenFVyk6o6IUiR8klt8/B4i2Mnxxw2DdMiI3t3HY0Zh++XZ6rOUmyO83h/m424Y/1riGdSgusIzGy7KhqHwZqFyMau49QPi3Ks6qgqoQeDN/3Xsre0cpdG5pxb8ENGCnqv8kVxPGeiZj0pgJXjnlHnAgMBAAECgYEAhdTYYgLxGecTyFrI/4QqF2FNAobVk9oeeV43eT4sQZ513QRDmtrnn9rjlU9HWiGIjd9+suUH9kzWo9MHeHU9mpoJf6IuvJYje3+Ec/ydkBZGdsPJnzdMXtrEF5v2SQUGMDbdjH1c9JhPQf/JHXca1VF5ubzSWPkEkJmSYj4heGECQQDd11BQkpXojPgNyKyw/DNUZfc65c49Ti1igovuZNpmS1sOpvxSSxAZmazZcJfAWFBKRaICOKCBmqkmr++PNKrXAkEAqD617SzYW8SJP3Fa1p2WMKxIpCp4Y7Lm2abfFuCgNzjGzGiZnxxorFZZ+I41qOdec7iiKciQocyhgRbsjMw/cQJBAM3cUJt0a8gxiL7Byf8zCi73sETnnEsnkNYpbtD6pfDnXMhsDRoQrhATm2LsKOZFDbzegUiuY8PhUbak7RlnNmECQClWLxC04fu6EBacXTs5wLr4uWhMXwPv4rQ7Qbi3O+YVdxKl6IilTDp7hOOC3UBAiH5aMM2fT5nRUyUKYtg9HqECQGvSyX3qX1z/teNCjawKnfxeH9Xo0M32PmRi5hS80zBvRgQqgfyaocrlvvjiArVBtwne1Eycc4xWBtQAK5DTpTk=";
////        String phone = RsaEncryptUtil.decrypt(encryptedPhone, rsaPrivateKey);
//        System.out.println(RsaEncryptUtil.decrypt(encrypt, rsaPrivateKey));
    }
}
